package bookstore.manager.impl;

import bookstore.bound.book.BookCreateForm;
import bookstore.bound.book.BookReviewForm;
import bookstore.bound.book.BookReviewRespForm;
import bookstore.manager.BookManager;
import bookstore.model.Book;
import bookstore.model.BookReview;
import bookstore.model.BookReviewItem;
import bookstore.model.BookReviewResp;
import bookstore.repository.BookRepository;
import bookstore.repository.BookReviewDao;
import bookstore.utils.SessionUtils;
import bookstore.utils.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;

@Service
public class BookManagerImpl implements BookManager {
    @Autowired
    protected BookRepository bookRepository;
    @Autowired
    protected BookReviewDao bookReviewDao;

    protected SessionUtils sessionUtils = new SessionUtils();

    // Create
    @Override
    public Map addNewBook(BookCreateForm bookCreateForm) {
        Book book = new Book();

        System.out.println(bookCreateForm.toString());

        book.setIsbn(bookCreateForm.getIsbn().trim());
        book.setName(bookCreateForm.getName().trim());
        book.setAuthor(bookCreateForm.getAuthor().trim());
        book.setHouse(bookCreateForm.getHouse().trim());
        book.setPubdate(bookCreateForm.getPubdate().trim());
        book.setPrice(Integer.parseInt(bookCreateForm.getPrice().replace(".", "").replace("￥", "").trim()));
        book.setSellPrice(Integer.parseInt(bookCreateForm.getSellPrice().replace(".", "").replace("￥", "").trim()));
        book.setStock(bookCreateForm.getStock());
        book.setDescription(bookCreateForm.getDesp().trim());

        System.out.println(book.toString());

        Map<String, Object> rsp = new HashMap<>();

        rsp.put("book", bookRepository.save(book));
        rsp.put("success", true);

        return rsp;
    }

    @Override
    public Map setBookSurface(ServletContext ctx, String isbn, Part filePart) {
        System.out.println(this.getClass().getName());
        Book book = bookRepository.findById(isbn).get();

        Map<String, String> mimeTable = new HashMap();
        mimeTable.put("image/png", ".png");
        mimeTable.put("image/bmp", ".bmp");
        mimeTable.put("image/gif", ".gif");
        mimeTable.put("image/jpeg", ".jpg");

        try {
            Path dir = Paths.get(ctx.getRealPath("/media/book"));
            System.out.println(dir.toString());

            String ext = mimeTable.get(Files.probeContentType(Paths.get(filePart.getSubmittedFileName())));
            File img = File.createTempFile(isbn, ext, dir.toFile());
            System.out.println(img.toPath().toString());

            try (InputStream input = filePart.getInputStream()) {
                Files.copy(input, img.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
            book.setSurface(img.getName());
        } catch (IOException err) {
            err.printStackTrace(System.err);
        }

        bookRepository.save(book);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", true);
        rsp.put("surface", book.getSurface());
        return rsp;
    }

    // Retrieve
    @Override
    public Map getBookDetail(String isbn) {
        Optional<Book> book = bookRepository.findById(isbn);
        Optional<BookReview> bookReview = bookReviewDao.findById(isbn);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("detail", book);
        rsp.put("review", bookReview);
        return rsp;
    }

    @Override
    public ArrayList getAllBooks() {
        return (ArrayList) bookRepository.findAll();
    }

    @Override
    public BookReview getBookReview(String isbn) {
        return bookReviewDao.findById(isbn).get();
    }

    // Update
    @Override
    public Map updateAuthor(String isbn, String author) {
        Book book = bookRepository.findById(isbn).get();
        book.setAuthor(author);
        bookRepository.save(book);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", book.getAuthor() == author);
        return rsp;
    }

    @Override
    public Map updateHouse(String isbn, String house) {
        Book book = bookRepository.findById(isbn).get();
        book.setHouse(house);
        bookRepository.save(book);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", book.getHouse() == house);
        return rsp;
    }

    @Override
    public Map updateStock(String isbn, int stock) {
        Book book = bookRepository.findById(isbn).get();
        book.setStock(stock);
        bookRepository.save(book);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", book.getStock() == stock);
        return rsp;
    }

    @Override
    public Map updateSellPrice(String isbn, int price) {
        Book book = bookRepository.findById(isbn).get();
        book.setSellPrice(price);
        bookRepository.save(book);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", book.getSellPrice() == price);
        return rsp;
    }

    @Override
    public Map AddReview(String isbn, HttpSession session, BookReviewForm bookReviewForm) {
        Long uid = sessionUtils.getProfile(session).map(UserInfo::getUserId).get();
        BookReviewItem item = new BookReviewItem(uid, bookReviewForm.getContent());

        BookReview bookReview = bookReviewDao.findById(isbn).orElse(new BookReview(isbn));
        bookReview.getReview().add(item);

        bookReviewDao.save(bookReview);

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", bookReview.getReview().indexOf(item) > -1);
        return rsp;
    }

    @Override
    public Map AddReviewResp(String isbn, HttpSession session, int reviewid, BookReviewRespForm bookReviewRespForm) {
        Boolean success = Boolean.FALSE;

        Long uid = sessionUtils.getProfile(session).map(UserInfo::getUserId).get();
        BookReviewResp bookReviewResp = new BookReviewResp(uid, bookReviewRespForm.getRespto(), bookReviewRespForm.getContent());

        BookReview bookReview = bookReviewDao.findById(isbn).get();
        List<BookReviewItem> reviewList = bookReview.getReview();

        for (BookReviewItem bookReviewItem : reviewList) {
            if (bookReviewItem.getId() == reviewid) {
                bookReviewItem.getSubReview().add(bookReviewResp);
                success = Boolean.TRUE;
            }
        }

        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", success);
        return rsp;
    }

    // Delete
    @Override
    public Map delete(String isbn) {
        Book book = bookRepository.findById(isbn).get();
        bookRepository.delete(book);

        Map<String, Boolean> rsp = new HashMap<>();
        rsp.put("success", !bookRepository.findById(isbn).isPresent());
        return rsp;
    }

}
